# function call方式
import os

import dotenv
from langchain_classic import hub

from langchain_classic.agents import create_tool_calling_agent, AgentExecutor, create_react_agent
from langchain_classic.memory import ConversationBufferMemory
from langchain_community.tools import TavilySearchResults
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import Tool
from langchain_openai import ChatOpenAI

def fun_1():
    dotenv.load_dotenv()

    # 获取Tavily实例
    search = TavilySearchResults(max_results=5)

    # 获取对应工具实例
    search_tool = Tool(
        name="search_tavily",
        description="使用Tavily进行搜索互联网上的信息,并将结果返回给用户",
        func=search.run,
    )

    # 获取大模型
    chat_model = ChatOpenAI(
        model=os.getenv("MODEL_NAME")
        , base_url=os.getenv("BASE_URL")
        , api_key=os.getenv("API_KEY")
        , temperature=0.8  # 精确度
        , max_tokens=1024  # 回答长度
    )

    # 提示词模板
    prompt_template = ChatPromptTemplate.from_messages([
        ("system", "你是一个AI助手，简短的回答问题，必要时使用search_tavily互联网工具查询")
        , ("human", "{input}")
        , ("placeholder", "{agent_scratchpad}")  # 这个参数必须要有的，包含代理执行过程中的中间步骤或思考过程
        , ("placeholder", "{history}") # 这个参数必须要有的,用来存储历史信息
    ])

    #创建记忆实例
    memory = ConversationBufferMemory(memory_key="history" , return_messages=True)

    # 获取Agent实例  create_tool_calling_agent()
    agent = create_tool_calling_agent(
        tools=[search_tool]
        , llm=chat_model
        , prompt=prompt_template
    )

    # 获取AgentExecutor实例
    agent_executor = AgentExecutor(
        agent=agent
        , tools=[search_tool]
        , verbose=True
        , memory=memory
        ,handle_parsing_errors= True  # 处理解析错误会用友好的方式显示错误，并降级处理。
    )

    # 调用invoke()得到响应
    response = agent_executor.invoke({"input": "今天的北京天气如何"})
    print(response)
    # 调用invoke()得到响应
    response = agent_executor.invoke({"input": "我刚才问的是哪个城市的天气？"})
    print(response)

#fun_1()

#ReAct模式
def fun_2():
    dotenv.load_dotenv()

    # 获取Tavily实例
    search = TavilySearchResults(max_results=5)

    # 获取对应工具实例
    search_tool = Tool(
        name="search_tavily",
        description="使用Tavily进行搜索互联网上的信息,并将结果返回给用户",
        func=search.run,
    )

    # 获取大模型
    chat_model = ChatOpenAI(
        model=os.getenv("MODEL_NAME")
        , base_url=os.getenv("BASE_URL")
        , api_key=os.getenv("API_KEY")
        , temperature=0.8  # 精确度
        , max_tokens=1024  # 回答长度
    )

    # 提示词模板
    # prompt_template = ChatPromptTemplate.from_messages([
    #     ("system" , "你是一个AI助手，简短的回答问题，必要时使用search_tavily互联网工具查询")
    #     ,("human" , "{input}")
    #     ,("placeholder", "{agent_scratchpad}") # 这个参数必须要有的，包含代理执行过程中的中间步骤或思考过程
    # ])

    # 提示词模板https://smith.langchain.com/hub/hwchase17/react-chat，ReAct模式有固定的参数，这里直接使用官方模板
    prompt_template = hub.pull("hwchase17/react-chat")

    # 创建记忆实例
    memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
    # 获取Agent实例  create_react_agent()
    agent = create_react_agent(
        tools=[search_tool]
        , llm=chat_model
        , prompt=prompt_template
    )

    # 获取AgentExecutor实例
    agent_executor = AgentExecutor(
        agent=agent
        , tools=[search_tool]
        , verbose=True
        , memory=memory
    )

    # 调用invoke()得到响应
    response = agent_executor.invoke({"input": "今天的北京天气如何"})
    print(response)
    response = agent_executor.invoke({"input": "我刚才问的是哪个城市的天气？"})
    print(response)


fun_2()